#include "object.h"
#include "common.h"
object::object()
{
    rotation.x=0;
    rotation.y=0;
    rotation.z=0;

    position.x=0;
    position.y=0;
    position.z=0;
    allocated=0;
    curtriangle=0;
    max_tnum=0;
    base=0;
    gmem=false;
    is_textured=true; ///going to just have to assume
    is_tex_loaded=false;


}

unsigned int object::cgid=0;


void object::allocate_triangles(int num)
{

    if(allocated==1)
    {
        delete [] triangles;
    }

    triangles=new triangle[num];

    allocated=1;

    max_tnum=num;

}

void object::gid_take()
{

    gid=cgid++;

}




void object::add_triangle(triangle &t)
{

    if(curtriangle<max_tnum)
    {
        triangles[curtriangle]=t;
        curtriangle++;

    }
    else
    {
        exit(3);
    }
    //else error triangle out of bounds of object triangle array

}

void object::add_triangle(vertex points[3])
{
    if(curtriangle<max_tnum)
    {
        triangles[curtriangle].setpoints(points);
        curtriangle++;
    }

}


void object::push()
{
    olist.push_back(this);
}

void object::rem()
{
    olist.remove(this);
}


triangle &object::get_triangle(int num)
{

    return triangles[num];
}


void object::gmem_push()
{

    cl_float4 *tstuff=new cl_float4[max_tnum * 12];

    for(unsigned int i=0; i<max_tnum; i++)
    {

        triangle *P=NULL;



        if(this->base==0)
        {
            //P=&T->get_triangle(i);
            P=&triangles[i];
        }
        else
        {
            exit(1212321);
        }


        for(int j=0; j<3; j++)
        {
            tstuff[i*12 + j].x=P->points[j].pos.x;
            tstuff[i*12 + j].y=P->points[j].pos.y;
            tstuff[i*12 + j].z=P->points[j].pos.z;
        }
        for(int j=3; j<6; j++)
        {
            tstuff[i*12 + j].x=P->points[j-3].normal.x;
            tstuff[i*12 + j].y=P->points[j-3].normal.y;
            tstuff[i*12 + j].z=P->points[j-3].normal.z;
        }
        for(int j=6; j<9; j++)
        {
            tstuff[i*12 + j].x=P->points[j-6].col.r;
            tstuff[i*12 + j].y=P->points[j-6].col.g;
            tstuff[i*12 + j].z=P->points[j-6].col.b;
        }
        for(int j=9; j<12; j++)
        {
            tstuff[i*12 + j].x=P->points[j-9].uvw.x;
            tstuff[i*12 + j].y=P->points[j-9].uvw.y;
            tstuff[i*12 + j].z=P->points[j-9].uvw.z;
        }

    }

    cl_uint *imsuretheresabettersolutionthanthis=new cl_uint[max_tnum];


    gmem=clCreateBuffer(cl::context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float4)*max_tnum*12, tstuff, &cl::error); ///check for failure

    gisdrawbuffer=clCreateBuffer(cl::context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(cl_uint)*max_tnum, imsuretheresabettersolutionthanthis, &cl::error); ///consider implementing this by global memory manager, auto realloc when new max obj triangle num
    ///Do i draw these triangles



    is_gmem=true;


    delete [] tstuff;

    delete [] imsuretheresabettersolutionthanthis;


    ///will need to be made more efficient for dynamic memory management on the cpu. Store tstuff (and all its constituent parts) when loaded?

    ///Or perhaps this is the first call, but save tstuff for later reuse after gmem is unloaded


}


void object::texture_load()
{

    sf::Image img;
    img.LoadFromFile(texname);

    texture=new cl_float4[img.GetHeight()*img.GetWidth()];

    tex_width=img.GetHeight();
    tex_height=img.GetWidth();



    for(int i=0; i<tex_width; i++)
    {
        for(int j=0; j<tex_height; j++)
        {
            sf::Color pixel;
            pixel=img.GetPixel(i, j);
            texture[i + tex_width * j].x=pixel.r;
            texture[i + tex_width * j].y=pixel.g;
            texture[i + tex_width * j].z=pixel.b;
            texture[i + tex_width * j].w=1;
        }
    }

    is_tex_loaded=true;

}

void object::texture_load(sf::Image &img)
{
    texture=new cl_float4[img.GetHeight()*img.GetWidth()];
    tex_width=img.GetHeight();
    tex_height=img.GetWidth();



    for(int i=0; i<tex_width; i++)
    {
        for(int j=0; j<tex_height; j++)
        {
            sf::Color pixel;
            pixel=img.GetPixel(i, j);
            texture[i + tex_width * j].x=pixel.r;
            texture[i + tex_width * j].y=pixel.g;
            texture[i + tex_width * j].z=pixel.b;
            texture[i + tex_width * j].w=1;
        }
    }

    is_tex_loaded=true;

}


void object::texture_load(cl_float4 *tex, int width, int height)
{


    texture=new cl_float4[width*height];
    tex_width=width;
    tex_height=height;

    for(int i=0; i<tex_width; i++)
    {
        for(int j=0; j<tex_height; j++)
        {

            texture[i + tex_width * j].x=tex[i+tex_width*j].x;
            texture[i + tex_width * j].y=tex[i+tex_width*j].y;
            texture[i + tex_width * j].z=tex[i+tex_width*j].z;
            texture[i + tex_width * j].w=1;
        }
    }



}


void object::gtex_push()
{
    cl_image_format fermat;
    fermat.image_channel_order=CL_RGBA;
    fermat.image_channel_data_type=CL_FLOAT;

    gtex=clCreateImage2D(cl::context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &fermat, tex_width, tex_height, 0, texture, NULL);
}

void object::gtex_del()
{

    clReleaseMemObject(gtex);

}
